﻿using System;

namespace CoreRay
{
    //-----------------------------------------------------------------------------------------
    /// <summary>
    /// Manages the creation of render regions used to distribute rendering to multiple threads 
    /// or processes.
    /// </summary>
    /// <remarks>
    /// This class is not thread-safe, so be carefull when calling this class from 
    /// multiple threads.
    /// </remarks>
    //-----------------------------------------------------------------------------------------

    public abstract class RenderRegionManager
    {
        //-----------------------------------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="RenderRegionManager"/> class.
        /// </summary>
        /// <param name="regionWidth">Width of the render region.</param>
        /// <param name="regionHeight">Height of the render region.</param>
        /// <param name="totalWidth">Total width of the final image.</param>
        /// <param name="totalHeight">Total height of the final image.</param>
        //-----------------------------------------------------------------------------------------

        protected RenderRegionManager(int regionWidth, int regionHeight, int totalWidth, int totalHeight)
        {
            if(regionWidth < 0)
            {
                throw new ArgumentException("Region width cannot be negative.", "regionWidth");
            }

            if(regionHeight < 0)
            {
                throw new ArgumentException("Region height cannot be negative.", "regionHeight");
            }

            if(totalWidth < 0)
            {
                throw new ArgumentException("Total width cannot be negative.", "totalWidth");
            }

            if(totalHeight < 0)
            {
                throw new ArgumentException("Total height cannot be negative.", "totalHeight");
            }

            if(totalWidth < regionWidth)
            {
                throw new ArgumentException("Total width cannot be smaller than region width.", "totalWidth");
            }

            if(totalHeight < regionHeight)
            {
                throw new ArgumentException("Total height cannot be smaller than region height.", "totalHeight");
            }

            this.TotalWidth = totalWidth;
            this.TotalHeight = totalHeight;
            this.RegionWidth = regionWidth;
            this.RegionHeight = regionHeight;
        }


        //-----------------------------------------------------------------------------------------
        /// <summary>
        /// Gets the width of render regions generated.
        /// </summary>
        /// <value>Width of the render regions.</value>
        //-----------------------------------------------------------------------------------------

        public int RegionWidth
        {
            get;
            private set;
        }


        //-----------------------------------------------------------------------------------------
        /// <summary>
        /// Gets the height of render regions generated.
        /// </summary>
        /// <value>Height of the render regions.</value>
        //-----------------------------------------------------------------------------------------

        public int RegionHeight
        {
            get;
            private set;
        }


        //-----------------------------------------------------------------------------------------
        /// <summary>
        /// Gets the total width of the final image.
        /// </summary>
        /// <value>Total width of the final image.</value>
        //-----------------------------------------------------------------------------------------

        public int TotalWidth
        {
            get;
            private set;
        }


        //-----------------------------------------------------------------------------------------
        /// <summary>
        /// Gets the total height of the final image.
        /// </summary>
        /// <value>Total height of the final image.</value>
        //-----------------------------------------------------------------------------------------

        public int TotalHeight
        {
            get;
            private set;
        }


        //-----------------------------------------------------------------------------------------
        /// <summary>
        /// Gets the next render region.
        /// </summary>
        /// <returns>Next render region.</returns>
        //-----------------------------------------------------------------------------------------

        public abstract RenderRegion GetNextRenderRegion();
    }
}
